iT邦幫忙

2025 iThome 鐵人賽

DAY 4
1
佛心分享-IT 人自學之術

30 天從 Python 轉職場 C# 新手入門系列 第 4

Day4-認識 C# 的資料型態與變數

  • 分享至 

  • xImage
  •  

前言

在程式設計中,「變數」就像一個容器,可以存放不同種類的資料。C# 作為一個強型別語言,每個變數在使用之前都需要先宣告其「資料型態」。今天,我們就來認識 C# 中的常見資料型態,以及如何在程式裡使用變數。


什麼是變數?

變數(Variable)就是一個具名的儲存空間,可以用來保存資料。例如:

  • 存放年齡(整數)
  • 存放姓名(文字)
  • 存放薪資(小數)

在 C# 中,宣告變數的語法是:

型態 變數名稱 = 初始值;

字串

宣告字串變數時,就直接用string來宣告此變數,由於是文字型態,所以要用""將內容包起來。

string firstFriend = "Maria";
string secondFriend = "Sage";
Console.WriteLine($"My friends are {firstFriend} and {secondFriend}");

https://ithelp.ithome.com.tw/upload/images/20250916/201787675Xr46VUhi6.png

字串不僅僅是字母的集合,可以使用 Length 來取得字串的長度。 Length 是字串的屬性,它會傳回該字串中的字元數:

Console.WriteLine($"The name {firstFriend} has {firstFriend.Length} letters.");
Console.WriteLine($"The name {secondFriend} has {secondFriend.Length} letters.");

https://ithelp.ithome.com.tw/upload/images/20250916/20178767dwrpmEQUGa.png

假設今天有一段字串包含了不想顯示的前導空格或尾隨空格,需要從字串中修剪這些空格,可以使用 Trim 來達到此目的,其中 TrimStart 和 TrimEnd 分別就是消除前面空格以及後面空格的方法。

string greeting = "      Hello World!       ";
Console.WriteLine($"[{greeting}]");

string trimmedGreeting = greeting.TrimStart();
Console.WriteLine($"[{trimmedGreeting}]");

trimmedGreeting = greeting.TrimEnd();
Console.WriteLine($"[{trimmedGreeting}]");

trimmedGreeting = greeting.Trim();
Console.WriteLine($"[{trimmedGreeting}]");

https://ithelp.ithome.com.tw/upload/images/20250916/20178767xStObo78sJ.png

接下來是 Replace 的功能,有就是我們日常會用到的「搜尋並取代」的功能。在 C# 裡的 Replace 方法就是做類似的事,它會幫你找到字串中的某個部分,然後換成你指定的新文字。這個方法需要兩個參數:第一個是要找的字串,第二個是要替換成的字串。

string sayHello = "Hello World!";
Console.WriteLine(sayHello);
sayHello = sayHello.Replace("Hello", "Greetings");
Console.WriteLine(sayHello);

https://ithelp.ithome.com.tw/upload/images/20250916/20178767BCy4Mnbok8.png
除此之外還有將字母全部轉成大寫跟小寫:

Console.WriteLine(sayHello.ToUpper());
Console.WriteLine(sayHello.ToLower());

https://ithelp.ithome.com.tw/upload/images/20250916/20178767ru5FqIDR3Z.png
最後是 Contains 這個方法,他是用來尋找字句裡是否有包含某個字詞,所以他回傳的是 true 跟 false 的布林值。

string songLyrics = "You say goodbye, and I say hello";
Console.WriteLine(songLyrics.Contains("goodbye"));
Console.WriteLine(songLyrics.Contains("greetings"));

https://ithelp.ithome.com.tw/upload/images/20250916/20178767A2RMSkrqAY.png


整數和浮點數

integer

先從最基礎的宣告整數變數以及最基本的加減乘除開始,宣告方式一樣,在最前面用 int 的方式來表示此變數為整是型態,接下來就可以進行一系列的運算並查看執行結果。會發現比較特別的現象是,即便答案是有小數點的,他還是會呈現為整數。

int a = 18;
int b = 6;
int c = a + b;
Console.WriteLine(c);

Output->24

int a = 5;
int b = 4;
int c = 2;
int d = a + b * c;
Console.WriteLine(d);

Output->13

d = (a + b) - 6 * c + (12 * 4) / 3 + 12;
Console.WriteLine(d);

Output->25

所以可以用%來呈現餘數:

int a = 7;
int b = 4;
int c = 3;
int d = (a + b) / c;
int e = (a + b) % c;
Console.WriteLine($"quotient: {d}");
Console.WriteLine($"remainder: {e}");

https://ithelp.ithome.com.tw/upload/images/20250916/20178767P5GLizPdkI.png

double

double 這個型別代表的是「雙精度浮點數」,其實它就是用來表示不是整數的數字,像是帶小數點的數,或者特別大、特別小的數值。至於「雙精度」的意思,就是電腦在儲存這種數字時,使用的二進位位數比「單精度」多一倍,所以精準度也更高。現在的電腦,大多數情況都會用雙精度 (double),而不是單精度 (float)。

double a = 5;
double b = 4;
double c = 2;
double d = (a + b) / c;
Console.WriteLine(d);

Output->4.5

double a = 19;
double b = 23;
double c = 8;
double d = (a + b) / c;
Console.WriteLine(d);

Output->5.25

decimal

還有一種類型需要學習:十進制 (decimal) 類型,十進制類型的取值範圍比雙精度類型小,但精度更高。做個簡單的比較:

double a = 1.0;
double b = 3.0;
Console.WriteLine(a / b);

decimal c = 1.0M;
decimal d = 3.0M;
Console.WriteLine(c / d);

https://ithelp.ithome.com.tw/upload/images/20250916/20178767b7VHr0nT3S.png


在 C# 中建立類型

Tuples

「Tuple(元組)」是一組固定長度、照順序排列的數值,裡面的每個元素都有自己的型別,而且可以選擇性地幫它取名字,可以透過以下範例來了解 Tuples:

var pt = (X: 1, Y: 2);

var slope = (double)pt.Y / (double)pt.X;
Console.WriteLine($"A line from the origin to the point {pt} has a slope of {slope}.");

可以看到結果如下:
https://ithelp.ithome.com.tw/upload/images/20250916/20178767DUqX2GVDNB.png
可以看到在定義 pt 這個變數時裡面同時包含了X、Y兩個int變數,並且可以用pt.X、pt.Y來調用參數。
我們可以重新定義 Tuples 中的任何成員,加上以下的程式碼可觀察差異:

pt.X = pt.X + 5;
Console.WriteLine($"The point is now at {pt}.");

結果:
https://ithelp.ithome.com.tw/upload/images/20250916/201787679je4PFmmmk.png

也可以使用 with 表達式建立一個新的元組,它是原始元組的修改副本。加入以下程式碼,可以看到執行結果的差異:

var pt2 = pt with { Y = 10 };
Console.WriteLine($"The point 'pt2' is at {pt2}.");

結果:
https://ithelp.ithome.com.tw/upload/images/20250916/20178767n2pneuFzFa.png
而在一個 Tuples 內不一定要是所有變數都是相同型態,例如:

var namedData = (Name: "Morning observation", Temp: 17, Wind: 4);
var person = (FirstName: "Lee", LastName: "Jessica");
var order = (Product: "guitar picks", style: "triangle", quantity: 500, UnitPrice: 0.10m);
Console.WriteLine($"My name is {person.LastName} {person.FirstName}. {namedData.Name} temp is {namedData.Temp} and wind is {namedData.Wind}.");

結果:
https://ithelp.ithome.com.tw/upload/images/20250916/20178767KIxSdn5V3f.png

record

前面提到的 Tuple 很適合把多個值放在同一個結構裡的時候使用,它很輕量,而且可以在需要的地方直接宣告來用。不過,隨著程式越寫越多,可能會發現同樣的 tuple 型別在程式裡重複出現。像是如果你的應用程式需要處理 2D 座標,那代表點的 tuple 可能就會一直被用到。若遇到這種情況時,其實可以改用 record 型別 來存這些值,還能提供更多功能。下面這個程式碼範例就是用 Main 方法當作程式的進入點,並且在它前面宣告一個 record 型別。

public record Point(int X, int Y);

public static void Main()
{
    Point pt = new Point(1, 1);
    var pt2 = pt with { Y = 10 };
    Console.WriteLine($"The two points are {pt} and {pt2}");
}

結果:
https://ithelp.ithome.com.tw/upload/images/20250916/201787677mE3RvEQqt.png

record 的宣告可以用一行程式碼就搞定,像這裡的 Point,它會把 X 和 Y 存在唯讀屬性裡。以後你只要用到這種型別,就直接寫 Point。有意義的名字(像 Point)能讓程式碼更好懂,也能看出用途。

在 Main 方法裡,你可以看到 with 的用法:它能複製一個既有的物件,然後只改想改的屬性。像 pt2 = pt with { Y = 10 } 這行,就表示「建立一個新的 pt2,裡面所有值跟 pt 一樣,只是 Y 改成 10」。而且 with 裡可以一次改好幾個屬性。

上面的 record 宣告只是一行程式碼,最後用 ; 結尾,就像一般的 C# 敘述一樣,也可以替 record 加更多功能,像是成員方法或更多資料欄位。

public record Point(int X, int Y)
{
    public double Slope() => (double)Y / (double)X;
}
public static void Main()
{
    Point pt = new Point(1, 1);
    var pt2 = pt with { Y = 10 };
    double slope = pt.Slope();
    Console.WriteLine($"The slope of {pt} is {slope}");
    Console.WriteLine($"The two points are {pt} and {pt2}");
}

結果:
https://ithelp.ithome.com.tw/upload/images/20250916/20178767ODAT27Xo3M.png

在 C# 裡,所有有名字的型別基本上都是 class 或 struct。

  • class 是參考型別(reference type)。變數裡存的是一個「參考」(可以想成是指向記憶體的指標),這個參考再指向實際存放資料的地方。
  • struct 則是數值型別(value type)。變數裡直接存放實際的內容。

舉例來說:

  • record struct Point 直接把 X 和 Y 這兩個整數存起來。
  • record class Point 則是存了一個參考,這個參考再指向 X 和 Y 的資料位置。

實際差別是:

  • 數值型別(struct):在指定(=)或傳遞時會整個複製一份資料。
  • 參考型別(class):指定時只會複製參考,結果指向的還是同一份資料。

record 關鍵字會幫你自動產生一些常用的功能,例如比較相等性、指定、複製等等。如果你的型別主要就是用來存放一組相關資料,那用 record 會很方便。

如果你的型別除了存值,還需要更進階的行為,可以考慮直接用 struct 或 class,不用加 record。

  • 用 struct:當你主要還是以存值為主,但需要多一些額外行為。
  • 用 class:當你要用到物件導向的封裝、繼承、多型等特性。

另外還有 interface(介面型別),它可以定義一組「行為契約」,讓不同的 struct 或 class 去實作。這樣就能讓程式更有彈性。

參考資料:點擊以打開


上一篇
Day3-第一個 C# 程式之延伸
下一篇
Day5-C# 的流程控制
系列文
30 天從 Python 轉職場 C# 新手入門6
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言